package c2.cross.business.championrace;

import c2.advanced.business.common.fight.InternalFightHandler;
import c2.advanced.share.TableFacade;
import c2.cross.business.CrossBody;
import c2.cross.business.base.CrossModule;
import c2.cross.business.base.CrossSubModule;
import c2.advanced.business.base.KvData;
import c2.cross.business.championrace.sub.*;
import c2.cross.business.ladder.LadderModule;
import cate.common.util.GameResult;
import cate.game.event.championrace.ChampionRaceTimerEvent;
import cate.game.framework.advanced.AdvancedLongAttributes;
import cate.game.play.support.PlayBuildContext;
import cate.game.pvp.championrace.ChampionRaceSpecUtils;
import cate.game.pvp.championrace.data.ChampionRaceRank;
import cate.game.pvp.championrace.data.*;
import cate.game.pvp.championrace.timer.ChampionRaceTimerTask;
import cate.game.role.RoleSnapshot;
import cate.game.util.IntervalCounter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Comparator;
import java.util.List;


@Slf4j
public class ChampionRaceModule extends CrossModule<ChampionRaceKv> {
    private final ChampionRaceMsgModule send = new ChampionRaceMsgModule();
    private final ChampionRaceRecvModule recv = new ChampionRaceRecvModule();
    private final ChampionRaceTimerModule timer = new ChampionRaceTimerModule();
    private final ChampionRacePullDataModule pull = new ChampionRacePullDataModule();
    private final ChampionRaceFightModule fight = new ChampionRaceFightModule();

    public ChampionRaceModule(CrossBody context) {
        super(context);
    }

    @Override
    protected String getStatusKey() {
        return KvData.KEY_CHAMPION_RACE;
    }

    @Override
    public String getName() {
        return "跨服冠军赛";
    }

    @Override
    protected CrossSubModule<?>[] getSubModules() {
        return new CrossSubModule[]{send, recv, timer, pull, fight};
    }

    public boolean hasRecvdRedPacket(ChampionRaceSpec spec, String roleUid) {
        return status.hasRecvdRedPacket(spec, roleUid);
    }

    public List<ChampionRaceRecord> queryRecords(ChampionRaceSpec spec) {
        return status.getRecords(spec);
    }

    public List<ChampionRaceRecord> queryRecords(ChampionRaceSpec from, ChampionRaceSpec to) {
        return status.getRecords(from, to);
    }

    public List<ChampionRaceRecord> queryRecords(String uid, ChampionRaceSpec from, ChampionRaceSpec to) {
        return status.getRecords(uid, from, to);
    }

    public ChampionRacePs findPs(String roleUid) {
        return status.findPs(roleUid);
    }

    public List<ChampionRaceOpponent> findPs(int srvId) {
        return status.findPs(srvId);
    }

    public ChampionRaceBetRecord queryBetRecord(ChampionRaceSpec spec) {
        return status.getBetRecord(spec);
    }

    public List<ChampionRaceBetRecord> getAllBetRecord() {
        return status.getAllBetRecord();
    }

    public void bet(ChampionRaceSpec spec, byte side, long coins) {
        status.bet(spec, side, coins);
    }

    public List<ChampionRaceTimerTask.Setting> getTimerSettings() {
        return status.getTimerSettings();
    }

    public int getSeason()  {
        return status.getSeason();
    }

    public long getCloseTime() {
        return status.getCloseTime();
    }

    public AdvancedLongAttributes getAttributes() {
        return status.getAttributes();
    }

    public long getOpenTime() {
        return status.getOpenTime();
    }

    private final IntervalCounter saveTrigger = new IntervalCounter(3600);

    @Override
    public void onInterval() {
        try{
            timer.onInterval();
            if (saveTrigger.trigger()) {
                if (!ChampionRaceSpecUtils.isFightingPeriod(getSpec().getPeriod())) {
                    saveStatus();
                }
            }
        } catch (Exception e) {
            log.error("跨服冠军赛定时异常啦");
        }
    }

    /**
     * 每N秒执行一次onInterval()
     */
    @Override
    protected int getIntervalSeconds() {
        return 1;
    }

    public void openSeason(ChampionRaceTimerTask.Setting setting) {
        status.openSeason(setting);
    }

    public void closeSeason(ChampionRaceTimerTask.Setting setting) {
        status.closeSeason(setting);
    }

    public void switchSeason(ChampionRaceTimerTask.Setting setting) {
        status.switchSeason(setting);
    }

    public boolean rankSettle(ChampionRaceTimerTask.Setting setting) {
        List<ChampionRacePs> psList = pull.pull();
        if (CollectionUtils.isNotEmpty(psList)) {
            return status.rankSettle(setting, psList);
        } else {
            return status.jumpRankSettle(setting);
        }
    }

    public List<ChampionRacePs> getSortedPs(Comparator<? super ChampionRacePs> comparator) {
        return status.getSortedPs(comparator);
    }

    public GameResult<Long> startFight(ChampionRaceRecord record, ChampionRacePs psA, ChampionRacePs psB) {
        return fight.startFight(record, psA, psB);
    }

    public boolean changeSpec(ChampionRaceTimerTask.Setting setting, int flag) {
        return changeSpec(setting, flag, true);
    }

    public boolean changeSpec(ChampionRaceTimerTask.Setting setting, int flag, boolean opSkip) {
        return status.changeSeasonSpec(setting, flag, opSkip);
    }

    public boolean canChangeSpec(ChampionRaceTimerTask.Setting setting, int flag) {
        return canChangeSpec(setting, flag, true);
    }

    public boolean canChangeSpec(ChampionRaceTimerTask.Setting setting, int flag, boolean opSkip) {
        return status.canChangeSeasonSpec(setting, flag, opSkip);
    }

    public void addRecordData(ChampionRaceRecord record) {
        status.addRecordData(record);
    }

    public void addBetRecordData(ChampionRaceBetRecord betRecord) {
        status.addBetRecordData(betRecord);
    }

    public PlayBuildContext getPlayBuildContext() {
        return context.play.getPlayBuildContext();
    }

    public InternalFightHandler getFightHandler() {
        return context.fightHandler;
    }

    public TableFacade getTableFacade() {
        return context.table;
    }

    public LadderModule getLadderModule() {
        return context.ladder;
    }

    public boolean settleRankReward() {
        return status.settleRankReward();
    }

    public void upsertVideo(ChampionRaceSpec spec, ChampionRaceVideo video) {
        status.upsertVideo(spec, video);
    }

    public ChampionRaceRank getRankData(String roleUid) {
        return status.getRankDate(roleUid);
    }

    public List<ChampionRaceRank> getRankList() {
        return status.getRankList();
    }

    public List<ChampionRaceRedPacketRecord> getRedPacket(ChampionRaceSpec spec, RoleSnapshot rs) {
        return status.getRedPacket(spec, rs);
    }

    public List<ChampionRaceRedPacketRecord> getRoleRedPacket(ChampionRaceSpec spec, String roleUid) {
        return status.getRoleRedPacket(spec, roleUid);
    }

    public List<ChampionRaceRankRwd> getRankRwdList(int season, int srvId) {
        return status.getRankRwdList(season, srvId);
    }

    public void updatePs(ChampionRacePs ps) {
        status.updatePs(ps);
    }

    public GameResult<Void> admire(int index, String roleUid) {
        return status.admire(index, roleUid);
    }

    public void dispatchTimerEvent(ChampionRaceSpec spec, ChampionRaceTimerEvent timerEvent) {
        send.dispatchTimerEvent(spec, timerEvent);
    }

    public List<ChampionRaceTimerEvent> getSpecTimerEvents(ChampionRaceSpec spec) {
        return send.getSpecEvents(spec);
    }

    public ChampionRaceSpec getSpec() {
        return status.getSpec();
    }
}
